package inputprocessor;

import org.apache.xerces.parsers.DOMParser;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.util.*;

/**
 * Uses the Xerces parser to implement an interface to the XML input file.
 * The XML input file is what the XQuery evaluation will eventually run against.
 * @author RaresMan
 *
 */
public class XMLNavigator
{
   /** 
    * Function to test the interface to our XML input file
    * @param args
    * @throws Exception
    */
   public static void main(String[] args) throws Exception
   {
	   String fileName = "input/test.xml";
	   Node root = root(fileName);
	  
	   System.out.println(root.getNodeName());
	   List<Node> rootChildren = children(root);
	   
	   for(Node child : rootChildren) {
		   if(child.getNodeType() == Node.ELEMENT_NODE) {
			   //System.out.println("\t" + child.getNodeName());
			   System.out.println("\t" + tag(child));
			   System.out.println("\t\t" + text(child));			  
		   }
	   }	         
   }

   /**
    * Given a filename to an XML document, reads the document in and returns
    * the root element of the document.
    * @param fileName
    * @return
    */
   public static Node root(String fileName) {
	   try {
          DOMParser p = new DOMParser();
          p.parse(fileName);
          Document doc = p.getDocument();
          Node n = doc.getDocumentElement();
          return n;          
       } catch (Exception e) {
    	   e.printStackTrace(); 
    	   return null;
       }
   }

   /**
    * Returns a list of the children of the specified nodes.
    * TODO@Rares: Check to make sure this is in document order
    * @param n
    * @return
    */
   public static List<Node> children(Node n) {
	   
	   NodeList propList = n.getChildNodes();
	   List<Node> normalList = new ArrayList<Node>();
	   
	   for(int i=0;i<propList.getLength();i++) {
		   Node childNode = propList.item(i);
		   normalList.add(childNode);
	   }

	   return normalList;
   }
   
   /**
    * Given a node n, returns a list containing the parent of that node, or
    * if the node has no parent, an empty list.
    * @param n
    * @return
    */
   public static List<Node> parent(Node n) {
	   
	   List<Node> parentList = new ArrayList<Node>();
	   
	   if(n.getParentNode() != null) {
		   parentList.add(n.getParentNode());
	   } 
	   
	   return parentList;
   }
   
   /**
    * Returns the tag associated with the specified node. Throws an exception 
    * if the node in question is not an element node.
    * @param n
    * @return
    * @throws Exception
    */
   public static String tag(Node n) throws Exception {
	   if(n.getNodeType() == Node.ELEMENT_NODE) {
		   return n.getNodeName();
	   } else {
		   throw new Exception("Node is not an element node");
	   }
   }
   
   /**
    * Returns the text associated with the specified element node. 
    * TODO@Rares: Make sure this isn't supposed to return the actual text node
    * @param n
    * @return
    * @throws Exception
    */
   public static String text(Node n) throws Exception {
	   if(n.getNodeType() == Node.ELEMENT_NODE) {
		   return n.getFirstChild().getNodeValue();
	   } else {
		   throw new Exception("Node is not an element node");
	   }
   }
}